package com.sjz.test2;

import java.util.Optional;

import org.junit.Test;

/*
 * 一、Optional 容器类：用于尽量避免空指针异常
 * 	Optional.of(T t) : 创建一个 Optional 实例
 * 	Optional.empty() : 创建一个空的 Optional 实例
 * 	Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则创建空实例
 * 	isPresent() : 判断是否包含值
 * 	orElse(T t) :  如果调用对象包含值，返回该值，否则返回t
 * 	orElseGet(Supplier s) :如果调用对象包含值，返回该值，否则返回 s 获取的值
 * 	map(Function f): 如果有值对其处理，并返回处理后的Optional，否则返回 Optional.empty()
 * 	flatMap(Function mapper):与 map 类似，要求返回值必须是Optional
 */
public class TestOptional {
	
	@Test
	public void test1(){
		//	Optional.of(T t) : 创建一个 Optional 实例
		Optional<Employee> op = Optional.of(new Employee());
		Employee emp = op.get();
		System.out.println(emp);
		System.out.println(emp.getName());
	}
	
	/***
	 * 这两种都会报错
	 * Optional.empty() : 创建一个空的 Optional 实例
	 */
	@Test
	public void test2(){
	 //	 Optional<Employee> op = Optional.ofNullable(null);
   ///		System.out.println(op.get());   //java.util.NoSuchElementException: No value present
		
       // Optional<Employee> op = Optional.empty();
       // System.out.println(op.get());//java.util.NoSuchElementException: No value present
	}
	
	
	/***
	 * Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则创建空实例
	 * isPresent() : 判断是否包含值
	 * orElse(T t) :  如果调用对象包含值，返回该值，否则返回t
	 * 	orElseGet(Supplier s) :如果调用对象包含值，返回该值，否则返回 s 获取的值
	 */
	@Test
	public void test3(){
		 
		Optional<Employee> op = Optional.ofNullable(null);
		if(op.isPresent()){   //表示的是有值才执行  现在是空  不会执行111  并且程序也不会报错
			System.out.println(111);
			System.out.println(op.get());
		}
		 
		/***
		Employee emp = op.orElse(new Employee("张三"));  //如果op有值的话，用以前的值  如果没有值的话，构建一个值
		System.out.println(emp);****/
		
		Employee emp2 = op.orElseGet(() -> new Employee());
		//orElseGet和orElse  功能类似  都是有值用以前的，没有的话，就创建一个 区别是orElse传入的是值对象
		//orElseGet传入的是函数式接口
		System.out.println(emp2);   
	}
	
	
	/***
	 * 	map(Function f): 如果有值对其处理，并返回处理后的Optional，否则返回 Optional.empty()
 * 	flatMap(Function mapper):与 map 类似，要求返回值必须是Optional
	 */
	@Test
	public void test4() {
		Optional<Employee> op = Optional.of(new Employee(101, "张三", 18, 9999.99));
		//Optional<String> op2 = op.map((x)->x.getName());
		Optional<String> op2 = op.map(Employee::getName);
		System.out.println(op2.get());
		System.out.println("*************************************");
		Optional<String> flatMap = op.flatMap((e)->Optional.of(e.getName()));
		System.out.println(flatMap.get());
	}
	
	@Test
	public void test5() {
		Man man = new Man();

		String name = getGodnessName(man);
		System.out.println(name);
	}

	// 需求：获取一个男人心中女神的名字 如果没有的话，会报错 空指针异常
	public String getGodnessName(Man man) {
		if (man != null) {
			Godness g = man.getGod();

			if (g != null) {
				return g.getName();
			}
		}

		return "苍老师";
	}

	public String getGodnessName1(Man man) {
		return man.getGod().getName();
	}
	
	
	// 运用 Optional 的实体类
	@Test
	public void test6() {
		//如果已经有了的话，那么就用已经有的值
		//Optional<Godness> godness = Optional.ofNullable(new Godness("林志玲"));
		//Optional<NewMan> op = Optional.ofNullable(new NewMan(godness));
		
		//如果没有值的话，会得到默认的值
		Optional<NewMan> op = Optional.ofNullable(null);
		String name = getGodnessName2(op);
		System.out.println(name);
	}

	public String getGodnessName2(Optional<NewMan> man) {
		return man.orElse(new NewMan()) //如果NewMan是null的话，创建一个对象
				.getGodness()   
				.orElse(new Godness("苍老师"))    //如果Godness是null的话，创建一个对象
				.getName();

	}
	
}
